﻿using System;
using System.Collections;
using System.Text.RegularExpressions;
using Assets.Scripts.GtsScripts;
using UnityEngine;
using UnityEngine.Networking;

// Token: 0x020001C5 RID: 453
public abstract class Micro : Humanoid
{
	// Token: 0x1700014A RID: 330
	// (get) Token: 0x0600098C RID: 2444 RVA: 0x00056DF3 File Offset: 0x00054FF3
	// (set) Token: 0x0600098D RID: 2445 RVA: 0x00056DFB File Offset: 0x00054FFB
	public bool isCrushed { get; protected set; }

	// Token: 0x0600098E RID: 2446 RVA: 0x00056E04 File Offset: 0x00055004
	protected override void Awake()
	{
		this.isMicro = true;
		this.gravity = base.gameObject.GetComponent<Gravity>();
		if (this.gravity == null)
		{
			this.gravity = base.gameObject.AddComponent<Gravity>();
		}
		this.capsule = base.GetComponent<CapsuleCollider>();
		base.movement = base.gameObject.AddComponent<MovementCharacter>();
		base.Awake();
		MicroManager.Instance.AddMicro(this);
	}

	// Token: 0x0600098F RID: 2447 RVA: 0x00056E79 File Offset: 0x00055079
	protected override void OnDestroy()
	{
		UnityEngine.Object.Destroy(base.GetComponent<Gravity>());
		MicroManager.Instance.RemoveMicro(base.id);
		base.OnDestroy();
	}

	// Token: 0x06000990 RID: 2448 RVA: 0x00056E9C File Offset: 0x0005509C
	public virtual void Crush(EntityBase entity, Micro.CollisionData collisionData)
	{
		if ((!GlobalPreferences.CrushNpcEnabled.value && !this.isPlayer) || (!GlobalPreferences.CrushPlayerEnabled.value && this.isPlayer))
		{
			return;
		}
		if (entity != null)
		{
			if (!GlobalPreferences.PlayerCrushingEnabled.value && entity.isPlayer)
			{
				return;
			}
			if (!GlobalPreferences.NpcMicroCrushingEnabled.value && !entity.isPlayer && entity.isMicro)
			{
				return;
			}
			if (!GlobalPreferences.NpcGtsCrushingEnabled.value && !entity.isPlayer && entity.isGiantess)
			{
				return;
			}
		}
		if (!this.isCrushed)
		{
			EventManager.SendEvent(new CrushEvent(this, entity));
			SoundManager.This.PlayCrushed(base.transform.position, base.Scale);
			this.isCrushed = true;
			this.ai.behaviorController.StopAllBehaviors();
			this.ai.DisableAI();
			this.ai.actionManager.ClearAll();
			AnimationManager.SetAnimatorController(this.anim, IOManager.Instance.microAnimatorController);
			this.anim.Play("Fall");
			base.transform.localScale = new Vector3(base.transform.localScale.x, base.transform.localScale.y / GlobalPreferences.CrushFlatness.value, base.transform.localScale.z);
			MicroLookAtController component = base.GetComponent<MicroLookAtController>();
			if (component != null && component.enabled)
			{
				component.LookAt(null);
			}
		}
		if (!this.capsule.isTrigger)
		{
			this.capsule.isTrigger = true;
			this.capsule.direction = 2;
			this.capsule.center = Vector3.zero;
			this.rbody.velocity = Vector3.zero;
			this.gravity.enabled = false;
			this.PlaceSelfBlood();
		}
		if (UnityEngine.Random.value < GlobalPreferences.CrushSurviveChance.value)
		{
			this.anim.SetInteger(Animator.StringToHash("survivedAnim"), UnityEngine.Random.Range(0, Micro.survivorAnimCount));
		}
		else
		{
			this.isDead = true;
		}
		this.anim.SetBool(Animator.StringToHash("survived"), !this.isDead);
		if (entity && entity.isGiantess)
		{
			this.PlaceGtsBlood(collisionData);
			float num = (GameController.globalSpeed != 0f) ? GameController.globalSpeed : 1f;
			if (GlobalPreferences.CrushStickDuration.value > 0f && UnityEngine.Random.value < GlobalPreferences.CrushStickChance.value && this.stuckTime + Micro.stuckCooldown / num < Time.time)
			{
				base.StartCoroutine(this.StuckRoutine(collisionData));
				return;
			}
		}
		this.stuckTime = Time.time;
		base.CancelInvoke("DestroyMe");
		base.Invoke("DestroyMe", GlobalPreferences.BodyDuration.value);
	}

	// Token: 0x06000991 RID: 2449 RVA: 0x000571C3 File Offset: 0x000553C3
	public void DestroyMe()
	{
		if (!this.isPlayer)
		{
			UnityEngine.Object.Destroy(base.gameObject);
		}
	}

	// Token: 0x06000992 RID: 2450 RVA: 0x000571DC File Offset: 0x000553DC
	protected void PlaceSelfBlood()
	{
		if (!GlobalPreferences.BloodEnabled.value || (this.bloodTime != Time.time && this.bloodTime + 1f > Time.time))
		{
			return;
		}
		RaycastHit raycastHit;
		if (!Physics.Raycast(base.transform.position + Vector3.up * base.Scale, Vector3.down, out raycastHit, base.Scale * 2f, Layers.pathfindingMask))
		{
			return;
		}
		Quaternion rotation = Quaternion.LookRotation(Vector3.ProjectOnPlane(this.myTransform.forward, raycastHit.normal), raycastHit.normal) * Quaternion.AngleAxis(UnityEngine.Random.value * 360f, Vector3.up);
		GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(NPCSpawner.Instance.blood, raycastHit.point + raycastHit.normal * base.Scale * 0.02f, rotation);
		gameObject.transform.localScale *= base.transform.lossyScale.y;
		UnityEngine.Object.Destroy(gameObject, GlobalPreferences.BloodDuration.value);
		this.bloodTime = Time.time;
	}

	// Token: 0x06000993 RID: 2451 RVA: 0x00057324 File Offset: 0x00055524
	protected void PlaceGtsBlood(Micro.CollisionData collisionData)
	{
		if (!GlobalPreferences.BloodEnabled.value || (this.bloodTime != Time.time && this.bloodTime + 1f > Time.time))
		{
			return;
		}
		Vector3 position;
		Quaternion quaternion;
		if (!this.GetCrushPositioning(collisionData, out position, out quaternion))
		{
			return;
		}
		quaternion *= Quaternion.AngleAxis(UnityEngine.Random.value * 360f, Vector3.up);
		GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(NPCSpawner.Instance.blood, position, quaternion, base.transform);
		if (BloodBounds.IsOddlyPlaced(gameObject.transform, collisionData.collider))
		{
			UnityEngine.Object.Destroy(gameObject, 0f);
		}
		else
		{
			UnityEngine.Object.Destroy(gameObject, GlobalPreferences.BloodDuration.value);
			this.bloodTime = Time.time;
			gameObject.transform.parent = collisionData.transform;
			Giantess componentInParent = collisionData.transform.GetComponentInParent<Giantess>();
			componentInParent.AddBlood(gameObject);
		}
	}

	// Token: 0x06000994 RID: 2452 RVA: 0x00057418 File Offset: 0x00055618
	private bool GetCrushPositioning(Micro.CollisionData collisionData, out Vector3 position, out Quaternion rotation)
	{
		Vector3 vector = collisionData.contacts[0].point;
		Vector3 vector2 = -collisionData.contacts[0].normal;
		float num = 2f * collisionData.collider.bounds.extents.magnitude;
		vector += num * -vector2;
		Ray ray = new Ray(vector, vector2);
		RaycastHit raycastHit;
		if (!collisionData.collider.Raycast(ray, out raycastHit, 2f * num))
		{
			position = Vector3.zero;
			rotation = Quaternion.identity;
			return false;
		}
		position = raycastHit.point + 0.001f * raycastHit.normal;
		rotation = Quaternion.LookRotation(Vector3.ProjectOnPlane(this.myTransform.forward, raycastHit.normal), raycastHit.normal);
		return true;
	}

	// Token: 0x06000995 RID: 2453 RVA: 0x00057508 File Offset: 0x00055708
	private float GetRandomStickDuration()
	{
		float value = GlobalPreferences.CrushStickDuration.value;
		float num = 90f / (1f - value) + 2f * value - 90f;
		float value2 = UnityEngine.Random.value;
		return num * (Mathf.Pow(2.1f * value2 - 0.84f, 3f) + value2 / 2f + 0.75f);
	}

	// Token: 0x06000996 RID: 2454 RVA: 0x0005756C File Offset: 0x0005576C
	private IEnumerator StuckRoutine(Micro.CollisionData collisionData)
	{
		Vector3 position;
		Quaternion rotation;
		if (this.GetCrushPositioning(collisionData, out position, out rotation))
		{
			this.rbody.constraints = RigidbodyConstraints.FreezeAll;
			base.transform.parent = collisionData.transform;
			base.transform.position = position;
			base.transform.rotation = rotation;
			this.stuckState = Micro.StuckState.STUCK;
			base.CancelInvoke("DestroyMe");
			if (GlobalPreferences.CrushStickDuration.value == 1f)
			{
				yield break;
			}
			this.peelOffTime = Time.time + this.GetRandomStickDuration();
			this.stuckTime = Time.time;
			yield return new WaitUntil(() => Time.time > this.peelOffTime);
			float distance = 1000f * collisionData.gameObject.transform.lossyScale.y;
			Vector3 offset = new Vector3(0f, distance, 0f);
			while (Physics.Raycast(base.transform.position + offset, Vector3.down, distance, Layers.pathfindingMask))
			{
				yield return new WaitForSeconds((GameController.globalSpeed != 0f) ? (0.1f / GameController.globalSpeed) : 10f);
			}
		}
		this.stuckTime = Time.time;
		if (this.stuckState != Micro.StuckState.STUCK)
		{
			yield break;
		}
		this.stuckState = Micro.StuckState.PEELING;
		this.anim.applyRootMotion = false;
		this.gravity.enabled = true;
		this.rbody.constraints = RigidbodyConstraints.None;
		this.rbody.isKinematic = false;
		this.rbody.angularDrag = 1f;
		this.rbody.collisionDetectionMode = CollisionDetectionMode.Continuous;
		this.capsule.isTrigger = false;
		base.Invoke("DestroyMe", GlobalPreferences.BodyDuration.value);
		yield break;
	}

	// Token: 0x06000997 RID: 2455 RVA: 0x00057590 File Offset: 0x00055790
	private IEnumerator StuckLandingRoutine()
	{
		this.stuckState = Micro.StuckState.SETTLING;
		this.rbody.angularDrag = 15f;
		yield return new WaitForSeconds(Micro.bodyLandingSettleDuration);
		this.EndSettling();
		yield break;
	}

	// Token: 0x06000998 RID: 2456 RVA: 0x000575AB File Offset: 0x000557AB
	private void EndSettling()
	{
		if (this.stuckState != Micro.StuckState.SETTLING)
		{
			return;
		}
		this.stuckState = Micro.StuckState.COMPLETE;
		this.rbody.collisionDetectionMode = CollisionDetectionMode.Discrete;
		this.stuckTime = Time.time;
	}

	// Token: 0x06000999 RID: 2457 RVA: 0x00002973 File Offset: 0x00000B73
	protected virtual void HandleGiantessContact()
	{
	}

	// Token: 0x0600099A RID: 2458 RVA: 0x000575D8 File Offset: 0x000557D8
	public override bool IsTargettable()
	{
		return !this.isDead && !this.IsStuck();
	}

	// Token: 0x0600099B RID: 2459 RVA: 0x000575F1 File Offset: 0x000557F1
	public bool IsStuck()
	{
		return this.stuckState == Micro.StuckState.STUCK;
	}

	// Token: 0x0600099C RID: 2460 RVA: 0x000575FC File Offset: 0x000557FC
	public virtual void StandUp()
	{
		if (!this.isCrushed)
		{
			return;
		}
		AnimationManager.SetAnimatorController(this.anim, IOManager.Instance.playerAnimatorController);
		this.anim.Play("wakeup");
		this.anim.applyRootMotion = true;
		this.rbody.isKinematic = false;
		this.rbody.constraints = RigidbodyConstraints.FreezeRotation;
		this.rbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
		if (!this.IsStuck())
		{
			base.transform.rotation = Quaternion.FromToRotation(base.transform.up, Vector3.up) * base.transform.rotation;
		}
		this.isDead = false;
		this.isCrushed = false;
		this.stuckState = Micro.StuckState.ALIVE;
		this.capsule.isTrigger = false;
		this.capsule.direction = 1;
		this.capsule.center = Vector3.up * this.capsule.height * 0.5f;
		this.gravity.enabled = true;
	}

	// Token: 0x0600099D RID: 2461 RVA: 0x00057709 File Offset: 0x00055909
	protected bool CheckDecisionCooldown()
	{
		return this.stuckTime + Micro.decisionCooldown < Time.time;
	}

	// Token: 0x0600099E RID: 2462 RVA: 0x0005771E File Offset: 0x0005591E
	public override bool CanDecide()
	{
		return !this.isDead && this.stuckState == Micro.StuckState.ALIVE;
	}

	// Token: 0x0600099F RID: 2463 RVA: 0x00057737 File Offset: 0x00055937
	public bool IsOnGround()
	{
		return this.IsOnLayer(Layers.pathfindingMask);
	}

	// Token: 0x060009A0 RID: 2464 RVA: 0x00057744 File Offset: 0x00055944
	public bool IsOnGiantess()
	{
		return this.IsOnLayer(Layers.gtsBodyMask);
	}

	// Token: 0x060009A1 RID: 2465 RVA: 0x00057754 File Offset: 0x00055954
	public bool IsOnLayer(LayerMask layerMask)
	{
		Vector3 point;
		Vector3 point2;
		float radius;
		PhysicsHelper.ProcessCapsule(this.capsule, out point, out point2, out radius);
		float num = this.capsule.bounds.size.y - base.Height * 0.1f;
		point.y += num;
		point2.y += num;
		RaycastHit raycastHit;
		return Physics.CapsuleCast(point, point2, radius, Vector3.down, out raycastHit, num + base.Height * 0.1f, layerMask);
	}

	// Token: 0x060009A2 RID: 2466 RVA: 0x000577E0 File Offset: 0x000559E0
	private void OnDrawGizmos()
	{
		if (this.IsOnGround())
		{
			Gizmos.DrawWireCube(base.transform.position, new Vector3(1f, 2f, 3f));
		}
		if (this.IsOnGiantess())
		{
			Gizmos.DrawWireCube(base.transform.position, new Vector3(2f, 3f, 1f));
		}
	}

	// Token: 0x060009A3 RID: 2467 RVA: 0x00002973 File Offset: 0x00000B73
	public virtual void OnStep(AnimationEvent e)
	{
	}

	// Token: 0x060009A4 RID: 2468 RVA: 0x0005784C File Offset: 0x00055A4C
	protected void OnTriggerEnter(Collider collider)
	{
		if (base.transform.parent == collider.transform)
		{
			return;
		}
		Vector3 a;
		Vector3 a2;
		float radius;
		PhysicsHelper.ProcessCapsule(this.capsule, out a, out a2, out radius);
		Vector3 extents = collider.bounds.extents;
		float num = Mathf.Min(Mathf.Min(extents.x, extents.y), extents.y);
		LayerMask mask = 1 << collider.gameObject.layer;
		Vector3[] array = new Vector3[]
		{
			Vector3.up,
			-Vector3.up,
			Vector3.forward,
			-Vector3.forward,
			Vector3.left,
			-Vector3.left
		};
		float num2 = -1f;
		RaycastHit hitInfo = default(RaycastHit);
		foreach (Vector3 vector in array)
		{
			RaycastHit raycastHit;
			if (Physics.CapsuleCast(a - vector * num, a2 - vector * num, radius, vector, out raycastHit, num, mask) && raycastHit.distance > num2)
			{
				num2 = raycastHit.distance;
				hitInfo = raycastHit;
			}
		}
		if (num2 == -1f)
		{
			return;
		}
		Micro.CollisionData collisionData = new Micro.CollisionData(hitInfo);
		this.OnCollisionEnter(collisionData);
	}

	// Token: 0x060009A5 RID: 2469 RVA: 0x000579F6 File Offset: 0x00055BF6
	protected void OnCollisionEnter(Collision collision)
	{
		this.OnCollisionEnter(new Micro.CollisionData(collision));
	}

	// Token: 0x060009A6 RID: 2470 RVA: 0x00057A04 File Offset: 0x00055C04
	protected void OnCollisionEnter(Micro.CollisionData collisionData)
	{
		bool flag = (GlobalPreferences.CrushNpcEnabled.value && !this.isPlayer) || (GlobalPreferences.CrushPlayerEnabled.value && this.isPlayer);
		GameObject gameObject = collisionData.gameObject;
		int layer = gameObject.layer;
		bool flag2 = layer == Layers.playerLayer;
		bool flag3 = layer == Layers.microLayer;
		bool flag4 = layer == Layers.gtsBodyLayer;
		if (this.stuckState == Micro.StuckState.PEELING)
		{
			if (flag3)
			{
				MicroNPC component = collisionData.gameObject.GetComponent<MicroNPC>();
				if (component != null && component.stuckState == Micro.StuckState.SETTLING)
				{
					component.EndSettling();
				}
			}
			else if (!flag4 && !flag2)
			{
				base.StartCoroutine(this.StuckLandingRoutine());
			}
		}
		if (layer == Layers.mapLayer || layer == Layers.defaultLayer || layer == Layers.buildingLayer)
		{
			if (this.stuckState == Micro.StuckState.STUCK)
			{
				this.PlaceSelfBlood();
				float value = GlobalPreferences.CrushStickChance.value;
				if (GlobalPreferences.CrushStickDuration.value == 1f)
				{
					return;
				}
				float a = Time.time + this.GetRandomStickDuration();
				float b = this.stuckTime + this.GetRandomStickDuration();
				float num = Mathf.Min(a, b);
				float num2 = Mathf.Max(a, b);
				this.peelOffTime = value * num2 + (1f - value) * num;
				Vector3 position;
				Quaternion rotation;
				if (this.peelOffTime < Time.time && this.GetCrushPositioning(collisionData, out position, out rotation))
				{
					this.rbody.constraints = RigidbodyConstraints.FreezeAll;
					base.transform.position = position;
					base.transform.rotation = rotation;
					this.stuckState = Micro.StuckState.COMPLETE;
					base.Invoke("DestroyMe", GlobalPreferences.BodyDuration.value);
				}
			}
			else
			{
				base.transform.parent = null;
			}
			return;
		}
		if (Regex.IsMatch(collisionData.transform.name, "U_CHAR\\d+") && GlobalPreferences.DebrisCanCrush.value)
		{
			this.Crush(null, collisionData);
		}
		if (flag && (flag2 || flag3))
		{
			Humanoid component2 = gameObject.GetComponent<Humanoid>();
			if (component2 && component2.Height > base.Height * 6f)
			{
				this.Crush(component2, collisionData);
			}
		}
		if (flag4)
		{
			GiantessBone component3 = gameObject.GetComponent<GiantessBone>();
			Giantess componentInParent = gameObject.transform.GetComponentInParent<Giantess>();
			if (componentInParent == null)
			{
				Debug.Log("GTS SCRIPT NOT FOUND!!!");
			}
			if (component3 == null)
			{
				return;
			}
			bool flag5 = this.IsOnGround();
			if (component3.isGrabbing && !flag5)
			{
				base.transform.parent = collisionData.transform;
				return;
			}
			if (flag && flag5 && component3.canCrush && component3.giantess.Height > base.Height * 10f)
			{
				if (flag3)
				{
					this.Crush(component3.giantess, collisionData);
				}
				else
				{
					for (int i = 0; i < collisionData.contacts.Length; i++)
					{
						if (collisionData.contacts[i].normal.y < -0.866f)
						{
							this.Crush(component3.giantess, collisionData);
							break;
						}
					}
				}
				return;
			}
			this.HandleGiantessContact();
			if (!flag5 && !this.isCrushed && !component3.giantess.poseMode)
			{
				base.transform.parent = collisionData.transform;
			}
		}
	}

	// Token: 0x060009A8 RID: 2472 RVA: 0x00002973 File Offset: 0x00000B73
	private void UNetVersion()
	{
	}

	// Token: 0x060009A9 RID: 2473 RVA: 0x00057DD0 File Offset: 0x00055FD0
	public override bool OnSerialize(NetworkWriter writer, bool forceAll)
	{
		bool flag = base.OnSerialize(writer, forceAll);
		bool flag2;
		return flag2 || flag;
	}

	// Token: 0x060009AA RID: 2474 RVA: 0x00057DE9 File Offset: 0x00055FE9
	public override void OnDeserialize(NetworkReader reader, bool initialState)
	{
		base.OnDeserialize(reader, initialState);
	}

	// Token: 0x04000F1D RID: 3869
	private static int survivorAnimCount = 2;

	// Token: 0x04000F1E RID: 3870
	private static float bodyLandingSettleDuration = 1f;

	// Token: 0x04000F1F RID: 3871
	private static float stuckCooldown = 0.5f;

	// Token: 0x04000F20 RID: 3872
	private static float decisionCooldown = 15f;

	// Token: 0x04000F21 RID: 3873
	protected Gravity gravity;

	// Token: 0x04000F22 RID: 3874
	protected CapsuleCollider capsule;

	// Token: 0x04000F24 RID: 3876
	private float peelOffTime;

	// Token: 0x04000F25 RID: 3877
	private float stuckTime;

	// Token: 0x04000F26 RID: 3878
	private float bloodTime;

	// Token: 0x04000F27 RID: 3879
	private Micro.StuckState stuckState;

	// Token: 0x020001C6 RID: 454
	private enum StuckState
	{
		// Token: 0x04000F29 RID: 3881
		ALIVE,
		// Token: 0x04000F2A RID: 3882
		STUCK,
		// Token: 0x04000F2B RID: 3883
		PEELING,
		// Token: 0x04000F2C RID: 3884
		SETTLING,
		// Token: 0x04000F2D RID: 3885
		COMPLETE
	}

	// Token: 0x020001C7 RID: 455
	public class CollisionData
	{
		// Token: 0x060009AB RID: 2475 RVA: 0x00057DF4 File Offset: 0x00055FF4
		public CollisionData(Collision collision)
		{
			this.collider = collision.collider;
			this.gameObject = collision.gameObject;
			this.transform = collision.transform;
			this.contacts = new Micro.ContactData[collision.contacts.Length];
			for (int i = 0; i < collision.contacts.Length; i++)
			{
				this.contacts[i] = new Micro.ContactData(collision.contacts[i]);
			}
		}

		// Token: 0x060009AC RID: 2476 RVA: 0x00057E78 File Offset: 0x00056078
		public CollisionData(RaycastHit hitInfo)
		{
			this.collider = hitInfo.collider;
			this.gameObject = hitInfo.collider.gameObject;
			this.transform = hitInfo.collider.gameObject.transform;
			this.contacts = new Micro.ContactData[1];
			this.contacts[0] = new Micro.ContactData(hitInfo);
		}

		// Token: 0x04000F2E RID: 3886
		public readonly Collider collider;

		// Token: 0x04000F2F RID: 3887
		public readonly Micro.ContactData[] contacts;

		// Token: 0x04000F30 RID: 3888
		public readonly GameObject gameObject;

		// Token: 0x04000F31 RID: 3889
		public readonly Transform transform;
	}

	// Token: 0x020001C8 RID: 456
	public class ContactData
	{
		// Token: 0x060009AD RID: 2477 RVA: 0x00057EDB File Offset: 0x000560DB
		public ContactData(ContactPoint contactPoint)
		{
			this.point = contactPoint.point;
			this.normal = contactPoint.normal;
		}

		// Token: 0x060009AE RID: 2478 RVA: 0x00057EFD File Offset: 0x000560FD
		public ContactData(RaycastHit hitInfo)
		{
			this.point = hitInfo.point;
			this.normal = hitInfo.normal;
		}

		// Token: 0x04000F32 RID: 3890
		public readonly Vector3 point;

		// Token: 0x04000F33 RID: 3891
		public readonly Vector3 normal;
	}
}
